#pragma once
#include <string>
#include <iostream>
#include <memory>
#include <jsoncpp/json/json.h>
#include "Log.hpp"

namespace ProtocolModule
{
    using LogModule::logger;
    using LogModule::LogLevel;

    const std::string ProtSep = " ";
    const std::string LineBreakSep = "\r\n";

    std::string Encode(const std::string &msg)
    {
        std::string len = std::to_string(msg.size());
        std::string package = len + LineBreakSep + msg + LineBreakSep;
        return package;
    }
    // 协议包装目标："len\r\n json串 \r\n"

    bool Decode(std::string &package, std::string *message)
    {
        // 除了要解包之外，还要判断数据报的完整性。
        // 1、判断是否取得到完整的长度。
        auto ret = package.find(LineBreakSep);
        if (ret == std::string::npos)
        {
            LOG(LogLevel::DEBUG) << "未找到标志\r\n, 解析失败";
            return false;
        }
            
            
        // 2、得到长度之后，判断是否可以得到完整的消息
        std::string lenmessage = package.substr(0, ret);
        int len = stoi(lenmessage);
        int totallen = len + lenmessage.size() + 2 * LineBreakSep.size();
        if (package.size() < totallen)
        {
            LOG(LogLevel::DEBUG) << "长度有误, 解析失败";
            return false;
        }
            
            
        *message = package.substr(ret + LineBreakSep.size(), len);
        package.erase(0, totallen);
        return true;
    }

    class Request
    {
    public:
        Request()
            : _data_x(0), _data_y(0), _oper(0)
        {
        }
        Request(int x, int y, char op)
            : _data_x(x), _data_y(y), _oper(op)
        {
        }

        void Debug()
        {
            std::cout << "_data_x: " << _data_x << std::endl;
            std::cout << "_data_y: " << _data_x << std::endl;
            std::cout << "_oper: " << _data_x << std::endl;
        }

        void Inc()
        {
            _data_x++;
            _data_y++;
        }

        // 结构化数据->字符串
        bool Serialize(std::string *out)
        {
            Json::Value root;
            root["datax"] = _data_x;
            root["datay"] = _data_y;
            root["oper"] = _oper;
            Json::FastWriter writer;
            *out = writer.write(root);

            // 移除末尾的换行符
            if (!out->empty() && out->back() == '\n')
            {
                out->pop_back();
            }
            return true;
        }

        // 字符串->结构化数据
        bool Deserialize(std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (res)
            {
                _data_x = root["datax"].asInt();
                _data_y = root["datay"].asInt();
                _oper = root["oper"].asInt();
            }
            return res;
        }

        int X() { return _data_x; }
        int Y() { return _data_y; }
        char Oper() { return _oper; }

    private:
        int _data_x;
        int _data_y;
        char _oper;
    };

    class Response
    {
    public:
        Response()
            : _result(0), _code(0)
        {
        }
        Response(int result, int code)
            : _result(result), _code(code)
        {
        }

        bool Serialize(std::string *msg)
        {
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter write;
            *msg = write.write(root);

            // 移除末尾的换行符
            if (!msg->empty() && msg->back() == '\n')
            {
                msg->pop_back();
            }
            return true;
        }

        bool Deserialize(std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (res)
            {
                _result = root["result"].asInt();
                _code = root["code"].asInt();
            }
            return res;
        }
        int GetResult() { return _result; }
        int GetCode() { return _code; }

        void SetResult(int res) { _result = res; }
        void SetCode(int code) { _code = code; }

        void ShowResponse()
        {
            std::cout << "result : " << _result << std::endl;
            std::cout << "code : " << _code << std::endl;
        }

    private:
        int _result;
        int _code;
    };

    class Factory
    {
    public:
        std::shared_ptr<Request> BuildRequest()
        {
            return std::make_shared<Request>();
        }

        std::shared_ptr<Request> BuildRequest(int x, int y, char op)
        {
            return std::make_shared<Request>(x, y, op);
        }

        std::shared_ptr<Response> BuildResponse()
        {
            return std::make_shared<Response>();
        }

        std::shared_ptr<Response> BuildResponse(int result, int code)
        {
            return std::make_shared<Response>(result, code);
        }
    };
}